#include "WrapLog.h"
#include "plist.h"
#include "MapConfig.h"

MapConfigMgr::PTR    gMapConfigMgr;
extern WrapLog::PTR gDailyLogger;

const vector<MapConfig::MapMonster>& MapConfig::getMonster(int degree) const
{
    static vector<MapConfig::MapMonster> snull;
    auto& it = mAllMonster.find(degree);
    if (it != mAllMonster.end())
    {
        return (*it).second;
    }
    else
    {
        return snull;
    }
}

void MapConfig::addMonster(int degree, int16_t typeID, double time, int times, int delay)
{
    auto& it = mAllMonster.find(degree);
    if (it == mAllMonster.end())
    {
        vector<MapMonster> tmp;
        mAllMonster[degree] = tmp;
    }

    mAllMonster[degree].push_back({ typeID, time , times, delay});
}

void MapConfigMgr::loadConfig()
{
    try
    {
        AnyValue* config = parsePlistByFileName("config_chap.plist");
        if (config != nullptr)
        {
            const PntDict* allMapConfig = config->asDict();
            for (const auto& oneMap : allMapConfig->getValue())
            {
                MapConfig::PTR mc = std::make_shared<MapConfig>();

                parseDegree(mc, oneMap.second->asDict()->dictValue("easy"), 1);
                parseDegree(mc, oneMap.second->asDict()->dictValue("normal"), 2);
                parseDegree(mc, oneMap.second->asDict()->dictValue("hard"), 3);

                mMapConfigs[strtol(oneMap.first.c_str(), nullptr, 10)] = mc;
            }
        }
    }
    catch (PlistParseError& e)
    {
        gDailyLogger->error("{}", e.what());
    }
}

MapConfig::PTR MapConfigMgr::getMapConfig(int16_t typeID)
{
    auto it = mMapConfigs.find(typeID);
    if (it != mMapConfigs.end())
    {
        return it->second;
    }
    else
    {
        return nullptr;
    }
}

void MapConfigMgr::parseDegree(MapConfig::PTR mc, const PntDict* data, int degree)
{
    if (data == nullptr)
    {
        return;
    }

    const PntArray* allMonster = data->arrayValue("roles");
    for (auto& oneMonster : allMonster->getValue())
    {
        const AnyValue* timeValue = oneMonster->asDict()->findValue("birthTime");
        const AnyValue* typeValue = oneMonster->asDict()->findValue("roleType");
        const AnyValue* timesValue = oneMonster->asDict()->findValue("times");
        const AnyValue* delayValue = oneMonster->asDict()->findValue("delay");

        int times = 1;
        double delay = 0;
        if (timesValue != nullptr)
        {
            times = timesValue->asInt()->getValue();
        }
        if (delayValue != nullptr)
        {
            if (delayValue->getType() == PNT_INT)
            {
                delay = delayValue->asInt()->getValue();
            }
            else if (delayValue->getType() == PNT_REAL)
            {
                delay = delayValue->asReal()->getValue();
            }
            else
            {
                assert(false);
            }
        }

        if (timeValue->getType() == PNT_INT)
        {
            mc->addMonster(degree, typeValue->asInt()->getValue(), timeValue->asInt()->getValue()*1000, times, delay*1000);
        }
        else
        {
            mc->addMonster(degree, typeValue->asInt()->getValue(), timeValue->asReal()->getValue() * 1000, times, delay * 1000);
        }
    }

    const PntDict* allDrops = data->dictValue("drops");
    for (auto& v : allDrops->getValue())
    {
        MonsterLoot::PTR monsterLoot = make_shared<MonsterLoot>();

        EffectConfigGroup::PTR effectGroup = make_shared<EffectConfigGroup>();
        string key = v.first;
        const PntArray* allVirtualItem = v.second->asArray();
        for (int i = 0; i < allVirtualItem->size(); ++i)
        {
            const PntDict* oneVirtualItem = (*allVirtualItem)[i]->asDict();
            int chance = oneVirtualItem->intValue("chance");
            int typeID = oneVirtualItem->intValue("itemType");
            if (typeID == 6)
            {
                int itemid = oneVirtualItem->intValue("id");
                effectGroup->addLoot(make_shared<AddItemEffect>(itemid, 1), chance);
            }
            else if (typeID == 1)
            {
                effectGroup->addLoot(make_shared<LockAttackEffect>(), chance);
            }
        }

        monsterLoot->addGroupLoot(effectGroup);
        mc->addMonsterLoot(degree, atoi(key.c_str()), monsterLoot);
    }
}